﻿using Apewer.Network;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace Apewer.Web
{

    /// <summary>用于网站的服务程序。</summary>
    public class HttpListenerProvider : ApiProvider<HttpListenerContext>
    {

        private HttpListenerContext context;
        private HttpListenerRequest request;
        private HttpListenerResponse response;

        /// <summary>HttpContext</summary>
        public override HttpListenerContext Context { get => context; }

        /// <summary>创建服务程序实例。</summary>
        /// <exception cref="ArgumentNullException"></exception>
        public HttpListenerProvider(HttpListenerContext context)
        {
            if (context == null) throw new ArgumentNullException(nameof(context));
            this.context = context;
            request = context.Request;
            response = context.Response;
        }

        #region Implement

        /// <summary>写入响应前的检查，返回错误信息。</summary>
        public override string PreWrite()
        {
            if (response == null) return null;

            // 从 Response 头中移除 Server 和 X-Powered-By 属性。
            var keys = new List<string>(response.Headers.AllKeys);
            if (keys.Contains("Server")) response.Headers.Remove("Server");
            if (keys.Contains("X-Powered-By")) response.Headers.Remove("X-Powered-By");

            return null;
        }

        /// <summary>向发送缓冲区的数据，之后停止并关闭响应流。</summary>
        public override void End() => End(true);

        #endregion

        #region Request

        /// <summary>获取 HTTP 方法。</summary>
        public override Network.HttpMethod GetMethod() => ApiUtility.Method(request.HttpMethod);

        /// <summary>获取客户端的 IP 地址。</summary>
        public override string GetClientIP() => request.UserHostAddress;

        /// <summary>获取请求的 URL。</summary>
        public override Uri GetUrl() => request.Url;

        /// <summary>获取请求的 Referrer。</summary>
        public override string GetReferrer() => request.UrlReferrer == null ? null : request.UrlReferrer.OriginalString;

        /// <summary>获取请求的头。</summary>
        public override HttpHeaders GetHeaders() => new HttpHeaders(request.Headers);

        /// <summary>获取请求的内容类型。</summary>
        public override string GetContentType() => request.ContentType;

        /// <summary>获取请求的内容长度。</summary>
        public override long GetContentLength() => request.ContentLength64;

        /// <summary>获取请求的内容。</summary>
        public override Stream RequestBody() => request.InputStream;

        #endregion

        #region Response

        /// <summary>设置 HTTP 状态。</summary>
        public override void SetStatus(int status, int subStatus = 0) => response.StatusCode = status;

        /// <summary>设置响应的头。</summary>
        public override string SetHeader(string name, string value)
        {
            if (response == null || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value)) return "参数无效。";
            try
            {
                response.AddHeader(name, value);
                return null;
            }
            catch (Exception ex) { return ex.Message; }
        }

        /// <summary>设置响应的缓存秒数，设置为 0 即不允许缓存。</summary>
        public override void SetCache(int seconds)
        {
            if (seconds > 0)
            {
                SetHeader("Cache-Control", $"public, max-age={seconds}, s-maxage={seconds}");
                return;
            }

            SetHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            SetHeader("Pragma", "no-cache");
        }

        /// <summary>设置响应的缓存秒数。</summary>
        public override void SetContentType(string value) => response.ContentType = value;

        /// <summary>设置响应的内容长度。</summary>
        public override void SetContentLength(long value) => response.ContentLength64 = value;

        /// <summary>设置响应重定向。</summary>
        /// <remarks>响应 302 状态。</remarks>
        public override void SetRedirect(string location)
        {
            try { response.Redirect(location); } catch { }
        }

        /// <summary>获取 Response 流。</summary>
        public override Stream ResponseBody() => response.OutputStream;

        #endregion

        #region This 

        /// <summary>停止并关闭响应流。可指定向发送缓冲区的数据。</summary>
        public void End(bool flush)
        {
            if (response == null) return;
            try { if (flush) response.OutputStream.Flush(); } catch { }
            try { response.Close(); } catch { }
        }

        /// <summary>获取 Cookies。</summary>
        public StringPairs GetCookies()
        {
            var sp = new StringPairs();
            if (request != null && request.Cookies != null)
            {
                for (var i = 0; i < request.Cookies.Count; i++)
                {
                    try
                    {
                        var cookie = request.Cookies[i];
                        var key = cookie.Name;
                        var value = cookie.Value ?? "";
                        sp.Add(new KeyValuePair<string, string>(key, value));
                    }
                    catch { }
                }
            }
            return sp;
        }

        /// <summary>设置响应的 Cookie。</summary>
        public string SetCookie(string key, string value)
        {
            if (response == null) return null;
            var k = key.ToTrim();
            var v = value.ToTrim();
            if (k.IsEmpty()) return "参数 Key 无效。";

            try
            {
                var cookie = new Cookie(k, v);
                var now = DateTime.Now;
                cookie.Expires = v.IsEmpty() ? now.AddDays(-1) : now.AddYears(1);
                response.SetCookie(cookie);
                return null;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        #endregion

    }

}
